use crate::common::models::OperationOrder;
use crate::common::{cs, orders};
use crate::database::dao;
use crate::common::constant::*;
use crate::common::cs::Error;
use crate::base;

pub async fn control_device(operation_order: OperationOrder) -> cs::Result<()>
{
    //查询信息 并将操作记录数据库
    let (port, address, device_type) = dao::select_device_info(operation_order.id).await?;
    if device_type == DEVICE_SWITCH as i32 {
        control_switch(operation_order.id, address, operation_order.operation, &port).await?;
    } else if device_type == DEVICE_PARALLELING_SWITCH as i32 {
        control_paralleling(operation_order.id, operation_order.operation, &port).await?;
    } else {
        return Err(Error::new("unsupported device type"));
    }
    Ok(())
}

/// 控制开关
async fn control_switch(device_id: i32, address: i32, operation: i32, port: &str) -> cs::Result<()>
{
    let open = match operation {
        OPERATION_OPEN => { true }
        OPERATION_CLOSE => { false }
        _ => { return Err(cs::Error::new(format!("unknown port : `{}`", &port))); }
    };
    //获取发送信道
    let sender = base::serial_sender_clone(port)
        .ok_or_else(|| cs::Error::new(format!("unknown port : `{}`", &port)))?;
    //获取命令
    let order = orders::switch_set_open(address as u8, open);
    //发送
    sender.send(order.to_vec().into_boxed_slice()).await?;
    dao::insert_operation(device_id, operation).await?;
    Ok(())
}

/// 控制并联开关
async fn control_paralleling(device_id: i32, operation: i32, port: &str) -> cs::Result<()>
{
    //获取命令
    let isc = base::serial_config().mapping.get(port)
        .ok_or_else(|| cs::Error::new(format!("unknown port : `{}`", &port)))?;
    let address = isc.paralleling_address.get(0)
        .ok_or_else(|| cs::Error::new(format!("unknown device id `{}` in port `{}`", device_id, &port)))?;
    let order = match match operation {
        OPERATION_OPEN_S1 => { orders::paralleling_set(address, 0, true) }
        OPERATION_CLOSE_S1 => { orders::paralleling_set(address, 0, false) }
        OPERATION_OPEN_S2 => { orders::paralleling_set(address, 1, true) }
        OPERATION_CLOSE_S2 => { orders::paralleling_set(address, 1, false) }
        OPERATION_OPEN_S3 => { orders::paralleling_set(address, 2, true) }
        OPERATION_CLOSE_S3 => { orders::paralleling_set(address, 2, false) }
        OPERATION_OPEN_ALL => { orders::paralleling_set_all(address, true) }
        OPERATION_CLOSE_ALL => { orders::paralleling_set_all(address, false) }
        _ => { return Err(cs::Error::new(format!("unknown operation : `{}`", operation))); }
    } {
        None => { return Err(cs::Error::new(format!("unknown address : `{}`", address))); }
        Some(o) => { o }
    };

    //获取发送信道
    let sender = base::serial_sender_clone(port)
        .ok_or_else(|| cs::Error::new(format!("unknown port : `{}`", &port)))?;

    //发送
    sender.send(order.to_vec().into_boxed_slice()).await?;
    dao::insert_operation(device_id, operation).await?;
    Ok(())
}